package com.erlinyou.travel.web.controller.user;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.amazonaws.services.securitytoken.model.Credentials;
import com.erlinyou.im.common.util.MD5Util;
import com.erlinyou.im.common.util.StringUtil;
import com.erlinyou.im.web.aspect.SystemLog;
import com.erlinyou.im.web.config.redis.JedisPoolUtils;
import com.erlinyou.im.web.config.session.SessionIndexMap;
import com.erlinyou.im.web.controller.base.LoginStatus;
import com.erlinyou.im.web.controller.base.ResultCode;
import com.erlinyou.im.web.controller.base.ResultJson;
import com.erlinyou.im.web.controller.base.ResultJsonBuild;
import com.erlinyou.im.web.controller.base.SiteUtil;
import com.erlinyou.im.web.controller.base.Source;
import com.erlinyou.im.web.vo.ChatMessageVo;
import com.erlinyou.im.web.vo.PushMessage;
import com.erlinyou.im.web.vo.PushMessage.PushMessageType;
import com.erlinyou.im.web.vo.user.AWSInfoVo;
import com.erlinyou.im.web.vo.user.UserInfoVo;
import com.erlinyou.im.web.wshandler.WSSManager;
import com.erlinyou.travel.model.user.TUser;
import com.erlinyou.travel.service.user.IUserService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import redis.clients.jedis.Jedis;
import springfox.documentation.annotations.ApiIgnore;

@Api(tags = { "User" })
@Controller
@RequestMapping(value = "/u")
@CrossOrigin(exposedHeaders={"xAuthToken"})
public class LoginController {
	private static Logger logger = LoggerFactory.getLogger(LoginController.class);
	@Resource
	private IUserService userService;
	
	@Resource
	private SessionRepository<?> sessionRepository;
	
	@SystemLog
	@ApiOperation(value="获取用户S3Token",notes = "获取s3 token")
	@PostMapping(value = "/getS3Token")
	@RequestMapping(value = "/getS3Token",method = {RequestMethod.POST})
	@ResponseBody
	public ResultJson<AWSInfoVo> getS3Token(@ApiIgnore HttpSession session) {
		TUser tUser = SiteUtil.getCurrUser(session);
		return new ResultJsonBuild<AWSInfoVo>().build(ResultCode.SUCCESS).setObj(getAWSInfo(tUser.getUserid()));
	}
	
	@SystemLog
	@ApiOperation(value="用户登录",notes = "用户登录")
	@ApiImplicitParams({
		@ApiImplicitParam(name="phone",required=true,value="用户手机", dataType="String",paramType="query"),
		@ApiImplicitParam(name="password",required=true,value="密码", dataType="String",paramType="query"),
		@ApiImplicitParam(name="source",required=true,value="来源",dataType="int",example="1",paramType="query")
	})
	@PostMapping(value = "/login")
	@ResponseBody
	public ResultJson<UserInfoVo> login(@ApiIgnore HttpSession session,
			@RequestParam(required=true)String phone,
			@RequestParam(required=true)String password,
			@RequestParam(required=true)Integer source) throws IOException {
		
		Source sourceEnum = Source.valueOf(source);
		if(sourceEnum == Source.UNKNOW){
			return new ResultJsonBuild<UserInfoVo>().build(ResultCode.LOGIN_SOURCE_ERROR);
		}
		
		TUser tUser = userService.findByPhone(phone);
		if(tUser != null){
			if(tUser.getPassword().equals(MD5Util.MD5(password))){
				boolean b = false;
				Jedis jedis = JedisPoolUtils.getJedis();
				jedis.select(1);
				String sbh = jedis.get(tUser.getUserid().toString());
				if(!StringUtil.isEmpty(sbh)) {
					if(!sbh.equals(tUser.getImei())) {
						b = true;
					}
				}
				Session oldSession = null;
				if(sessionRepository instanceof RedisOperationsSessionRepository){
					RedisOperationsSessionRepository redisOperationsSessionRepository = (RedisOperationsSessionRepository) sessionRepository;
					Map<String, ? extends Session> usersSessions = redisOperationsSessionRepository.
							findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, phone);
					oldSession = getOldSession(sourceEnum, usersSessions);
				}else{
					Map<String, Session> usersSessions = SessionIndexMap.get(phone);
					oldSession = getOldSession(sourceEnum, usersSessions);
				}
				//清除旧的session
				if(oldSession!=null){
					ChatMessageVo chatMessageVo = new ChatMessageVo();chatMessageVo.setType(1111);
					String pushContent = new PushMessage<>(PushMessageType.OUTLINE).buildJson();
					if(b) {
						WSSManager.sendMessageText(tUser.getUserid(), pushContent);
					}
					sessionRepository.deleteById(oldSession.getId());
				}
				
				session.setAttribute(SiteUtil.AUTHENTICATION_KEY, tUser);
				session.setAttribute(SiteUtil.SOURCE, source);
				session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, phone);
				
				UserInfoVo userInfo = new UserInfoVo();
				userInfo.setImage(tUser.getImage());
				userInfo.setNickName(tUser.getNickName());
				userInfo.setUserid(tUser.getUserid());
				tUser.setState(LoginStatus.login);
				jedis.set(tUser.getUserid().toString(), tUser.getImei());
				boolean flag = userService.save(tUser)!=null;
				
				jedis.close();
				if(!flag) {
					return new ResultJsonBuild<UserInfoVo>().build(ResultCode.UNKONW_ERROR);
				}
				logger.info(phone+" 登录成功");
				return new ResultJsonBuild<UserInfoVo>().build(ResultCode.SUCCESS).setObj(userInfo);
			}
		}
		return  new ResultJsonBuild<UserInfoVo>().build(ResultCode.LOGIN_FAIL);
	}
	@SystemLog
	@ApiOperation(value="用户id登录",notes = "用户id登录")
	@ApiImplicitParams({
		@ApiImplicitParam(name="userid",required=true,value="用户id", dataType="String",paramType="query"),
		@ApiImplicitParam(name="password",required=true,value="密码", dataType="String",paramType="query"),
		@ApiImplicitParam(name="source",required=true,value="来源",dataType="int",example="1",paramType="query")
	})
	@PostMapping(value = "/loginById")
	@ResponseBody
	public ResultJson<UserInfoVo> loginById(@ApiIgnore HttpSession session,
			@RequestParam(required=true)String userid,
			@RequestParam(required=true)String password,
			@RequestParam(required=true)Integer source) throws IOException {
		
		Source sourceEnum = Source.valueOf(source);
		if(sourceEnum == Source.UNKNOW){
			return new ResultJsonBuild<UserInfoVo>().build(ResultCode.LOGIN_SOURCE_ERROR);
		}
		
		TUser tUser = userService.findByUserid(Long.valueOf(userid));
		if(tUser != null){
			if(tUser.getPassword().equals(password)){
				boolean b = false;
				Jedis jedis = JedisPoolUtils.getJedis();
				jedis.select(1);
				String sbh = jedis.get(tUser.getUserid().toString());
				if(!StringUtil.isEmpty(sbh)) {
					if(!sbh.equals(tUser.getImei())) {
						b = true;
					}
				}
				Session oldSession = null;
				if(sessionRepository instanceof RedisOperationsSessionRepository){
					RedisOperationsSessionRepository redisOperationsSessionRepository = (RedisOperationsSessionRepository) sessionRepository;
					Map<String, ? extends Session> usersSessions = redisOperationsSessionRepository.
							findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, userid);
					oldSession = getOldSession(sourceEnum, usersSessions);
				}else{
					Map<String, Session> usersSessions = SessionIndexMap.get(userid);
					oldSession = getOldSession(sourceEnum, usersSessions);
				}
				//清除旧的session
				if(oldSession!=null){
					String pushContent = new PushMessage<>(PushMessageType.OUTLINE).buildJson();
					if(b) {
						WSSManager.sendMessageText(tUser.getUserid(), pushContent);
					}
					sessionRepository.deleteById(oldSession.getId());
				}
				
				session.setAttribute(SiteUtil.AUTHENTICATION_KEY, tUser);
				session.setAttribute(SiteUtil.SOURCE, source);
				session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, userid);
				
				UserInfoVo userInfo = new UserInfoVo();
				userInfo.setImage(tUser.getImage());
				userInfo.setNickName(tUser.getNickName());
				userInfo.setUserid(tUser.getUserid());
				tUser.setState(LoginStatus.login);
				jedis.set(tUser.getUserid().toString(), tUser.getImei());
				
				boolean flag = userService.save(tUser)!=null;
				
				jedis.close();
				if(!flag) {
					return new ResultJsonBuild<UserInfoVo>().build(ResultCode.UNKONW_ERROR);
				}
				logger.info(userid+" 登录成功");
				return new ResultJsonBuild<UserInfoVo>().build(ResultCode.SUCCESS).setObj(userInfo);
			}
		}
		return  new ResultJsonBuild<UserInfoVo>().build(ResultCode.LOGIN_FAIL);
	}
	
	
	@SystemLog
	@ApiOperation(value="登陆后验证token是否有效",notes = "登陆后验证token是否有效")
	@ApiImplicitParams({
	})
	@PostMapping(value = "/isEnabled")
	@ResponseBody
	@Deprecated
	public ResultJson<Object> isEnabled(@ApiIgnore HttpSession session) throws IOException {
		return ResultJsonBuild.buildObj(ResultCode.SUCCESS);
	}
	@SystemLog
	@ApiOperation(value="登陆后验证token是否有效",notes = "登陆后验证token是否有效")
	@ApiImplicitParams({
	})
	@PostMapping(value = "/loginOut")
	@ResponseBody
	public ResultJson<Object> loginOut(@ApiIgnore HttpSession session,HttpServletRequest request) throws IOException {
		TUser tUser = SiteUtil.getCurrUser(request);
		tUser.setState(LoginStatus.loginout);
		boolean flag = userService.save(tUser)!=null;
		
		return flag?ResultJsonBuild.buildObj(ResultCode.SUCCESS):ResultJsonBuild.buildObj(ResultCode.UNKONW_ERROR);
	}
	
	
	
	private Session getOldSession(Source sourceEnum, Map<String, ? extends Session> usersSessions) {
		if(usersSessions != null){
			Collection<? extends Session> sessions = usersSessions.values();
			for (Session userOldSession : sessions) {
				if(SiteUtil.getSource(userOldSession) == sourceEnum){
					return userOldSession;
				}
			}
		}
		return null;
	}
	
	private AWSInfoVo getAWSInfo(Long userId){
		Credentials credentials = S3Util.getCredentials(userId.toString());
		AWSInfoVo awsInfo = new AWSInfoVo();
		BeanUtils.copyProperties(credentials, awsInfo);
		awsInfo.setBucket(S3Util.DEFAULT_BUCKET);
		return awsInfo;
	}
}
